home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
DIZZY
/
SRC
/
SIMFILE.C
< prev
next >
Wrap
Text File
|
1991-10-04
|
14KB
|
614 lines
/*
>> Dizzy 1.0 SimFile.c
>>
>> A digital circuit simulator & design program for the X Window System
>>
>> Copyright 1990 Juri Munkki, all rights reserved
>>
>> Please read the included file called "DizzyDoc" for information on
>> what your rights are concerning this product.
>>
>> This file contains all file-handling routines for Dizzy.
*/
#include "dizzy.h"
#include <stdio.h>
#ifndef MACINTOSH
extern char CurFileName[]; /* Used only for Unix, */
extern char *DestFileName; /* see xstuff.h */
#endif
/*
>> Given a pointer to the element structure,
>> a position and a width, this routine fills
>> out the rectangle parts of the structure by
>> assuming that it follows a standard format.
*/
void PresetElement(newel,x,y,width)
register Element *newel;
int x,y;
int width;
{
int pinheight;
int inoff,outoff;
pinheight=newel->Inputs>newel->Outputs ?
newel->Inputs :
newel->Outputs;
inoff=(pinheight-newel->Inputs)*8;
outoff=(pinheight-newel->Outputs)*8;
newel->Flags=0;
newel->Body.top=y;
newel->Body.bottom=y+pinheight*16;
newel->Body.left=x;
newel->Body.right=x+width;
newel->InRect.left=x-8;
newel->InRect.right=x;
newel->InRect.top=y+inoff;
newel->InRect.bottom=newel->InRect.top+newel->Inputs*16;
newel->OutRect.left=newel->Body.right;
newel->OutRect.right=newel->Body.right+13;
newel->OutRect.top=y+outoff;
newel->OutRect.bottom=newel->OutRect.top+newel->Outputs*16;
}
/*
>> Open a file, read in all the available data into the
>> current header and return. If an error occurs, this
>> routine just quits. Someone could add better error handling.
*/
void OpenFile(thefile)
FILE *thefile;
{
int version;
long obtype;
int x,y;
register Element *newel;
int ins;
long esize;
Input *InArray;
int InputCount,OutputCount;
InputCount=0;
OutputCount=0;
if(thefile)
{ if(fscanf(thefile,"Dizzy %d\n",&version))
{ do
{ fread(&obtype,sizeof(char),4,thefile);
fscanf(thefile," %d %d ",&x,&y);
switch(obtype)
{ case ORIG:
fscanf(thefile,"\n");
CurHeader->XOrig=x;
CurHeader->YOrig=y;
break;
case INPT:
case CLOK:
case ONE_:
case ZERO:
newel=SimAllocate(sizeof(Element));
newel->Flags=0;
newel->Type=obtype;
newel->Length=sizeof(Element);
newel->Inputs=0;
newel->Outputs=1;
newel->Out[0].Data=0;
PresetElement(newel,x,y,16);
switch(obtype)
{ case INPT:
newel->PrivData= ++InputCount;
fscanf(thefile,"%d\n",&newel->Out[0].Data);
break;
case CLOK:
fscanf(thefile,"%d\n",&newel->PrivData);
break;
}
break;
case AND_:
case NAND:
case OR__:
case NOR_:
case XOR_:
case NXOR:
fscanf(thefile,"%d",&ins);
esize=sizeof(Element)+sizeof(Input)*ins;
newel=SimAllocate(esize);
newel->Flags=0;
newel->Type=obtype;
newel->Length=esize;
newel->Inputs=ins;
newel->Outputs=1;
PresetElement(newel,x,y,32);
InArray=(Input *)&(newel->Out[1]);
while(ins--)
{ fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
InArray++;
}
fscanf(thefile,"\n");
if(obtype==NAND || obtype==NOR_ || obtype==NXOR)
{ newel->Flags |= INVERTED;
}
break;
case RS__:
case D___:
case JK__:
if(obtype==JK__) ins=3;
else ins=2;
esize=sizeof(Element)+sizeof(Output)+sizeof(Input)*ins;
newel=SimAllocate(esize);
newel->Type=obtype;
newel->Flags=0;
newel->Length=esize;
newel->Inputs=ins;
newel->Outputs=2;
PresetElement(newel,x,y,32);
InArray=(Input *)&(newel->Out[2]);
while(ins--)
{ fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
InArray++;
}
fscanf(thefile,"\n");
break;
case CONN:
esize=sizeof(Element)+sizeof(Input);
newel=SimAllocate(esize);
InitConnector(newel,x,y);
InArray=(Input *)&(newel->Out[1]);
ins=fscanf(thefile,"%ldP%d\n",&(InArray->Chip),&(InArray->Pin));
break;
case OUTP:
case NOT_:
esize=sizeof(Element)+sizeof(Input);
newel=SimAllocate(esize);
newel->Flags=0;
newel->Type=obtype;
newel->Length=esize;
newel->Inputs=1;
newel->Outputs=1;
InArray=(Input *)&(newel->Out[1]);
fscanf(thefile,"%ldP%d\n",&(InArray->Chip),&(InArray->Pin));
PresetElement(newel,x,y,16);
if(obtype==NOT_)
{ newel->Flags |= INVERTED;
}
else
{ newel->PrivData= ++OutputCount;
}
break;
case HEXD:
esize=sizeof(Element)-sizeof(Output)+4*sizeof(Input);
newel=SimAllocate(esize);
newel->Type=obtype;
newel->Flags=0;
newel->Length=esize;
newel->Inputs=4;
newel->Outputs=0;
newel->PrivData=0;
PresetElement(newel,x,y,16);
InArray=(Input *)&(newel->Out[0]);
for(ins=0;ins<4;ins++)
{ fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
InArray++;
}
fscanf(thefile,"\n");
break;
case CUST:
{ unsigned char name[MAXFILENAME];
int i;
fgets((char *)name,MAXFILENAME-1,thefile);
i= -1;
while(name[++i]!=0)
{ if(name[i]<32) name[i]=0;
}
newel=InsertCustomChip((char *)name,x,y);
fscanf(thefile," %d",&ins);
InArray=(Input *)&(newel->Out[newel->Outputs]);
if(ins>newel->Inputs)
i=newel->Inputs;
else
i=ins;
while(i--)
{ fscanf(thefile," %ldP%d",&(InArray->Chip),&(InArray->Pin));
InArray++;
}
i=ins-newel->Inputs;
while(i-->0)
{ fscanf(thefile," %*ldP%*d");
}
fscanf(thefile,"\n");
}
case ENDF:
break;
default:
CurHeader->Last=CurHeader->First;
fclose(thefile);
return;
}
} while(obtype!=ENDF && !feof(thefile) && !ferror(thefile));
CurHeader->Last=SimEnd+SimPtr-SimBase;
AssignNumbers();
IndexToOffset();
}
fclose(thefile);
}
}
/*
>> Write the main header to a file. This routines doesn't
>> report any errors. Here's your chance to make dizzy better!
*/
void WriteFile(filename)
char *filename;
{
FILE *thefile;
int version;
register Element *newel;
int i;
Input *ip;
long offs;
Element *elem;
thefile=fopen(filename,"w");
if(thefile)
{ fprintf(thefile,"Dizzy 1\n");
fprintf(thefile,"ORIG %d %d\n",MainHeader->XOrig,MainHeader->YOrig);
DatabaseCleanup();
AssignNumbers();
OffsetToIndex();
for(offs=MainHeader->First;offs<MainHeader->Last;offs+=elem->Length)
{ elem=(Element *)(SimBase+offs);
ip=(Input *)&elem->Out[elem->Outputs];
fwrite(&elem->Type,sizeof(char),4,thefile);
if(elem->Type == CONN)
{ fprintf(thefile," %d %d ",elem->Body.left+4,elem->Body.top+4);
}
else
{ fprintf(thefile," %d %d ",elem->Body.left,elem->Body.top);
}
switch(elem->Type)
{ case INPT:
fprintf(thefile,"%d\n",elem->Out[0].Data & NEWVALUE);
break;
case ONE_:
case ZERO:
fprintf(thefile,"\n");
break;
case CLOK:
fprintf(thefile,"%d\n",elem->PrivData);
break;
case AND_:
case NAND:
case OR__:
case NOR_:
case XOR_:
case NXOR:
fprintf(thefile,"%d",elem->Inputs);
for(i=0;i<elem->Inputs;i++)
{ fprintf(thefile," %dP%d",(int)ip->Chip,ip->Pin);
ip++;
}
fprintf(thefile,"\n");
break;
case RS__:
case D___:
case JK__:
case CONN:
case OUTP:
case NOT_:
case HEXD:
for(i=0;i<elem->Inputs;i++)
{ fprintf(thefile," %dP%d",(int)ip->Chip,ip->Pin);
ip++;
}
fprintf(thefile,"\n");
break;
case CUST:
{ TableHeader *customheader;
customheader=(TableHeader *)(elem->Inputs+(Input *)&elem->Out[elem->Outputs]);
fprintf(thefile,"%s\n",customheader+1);
fprintf(thefile," %d",elem->Inputs);
for(i=0;i<elem->Inputs;i++)
{ fprintf(thefile," %dP%d",(int)ip->Chip,ip->Pin);
ip++;
}
fprintf(thefile,"\n");
}
break;
}
}
IndexToOffset();
fprintf(thefile,"END.\n");
fclose(thefile);
}
}
/*
>> Prompt for a filename and open that file, is user said it's ok.
*/
void PromptOpenFile()
{
FILE *thefile;
#ifdef MACINTOSH
long thetype;
Point thepoint = {80,160};
char name[256];
int vrefnum;
thetype='TEXT';
SFGetFile(thepoint,"\p",0L,1,&thetype,0L,&NameOfOpenFile);
if(NameOfOpenFile.good)
{
CurHeader->XOrig=0;
CurHeader->YOrig=0;
SimEnd=CurHeader->First;
CurHeader->Last=CurHeader->First;
FileIsNamed= -1;
GetVol(name,&vrefnum);
SetVol(0L,NameOfOpenFile.vRefNum);
BlockMove(1+NameOfOpenFile.fName,name,NameOfOpenFile.fName[0]);
name[NameOfOpenFile.fName[0]]=0;
SetWTitle(MyWind,NameOfOpenFile.fName);
thefile=fopen(name,"r");
OpenFile(thefile);
SetVol(0L,vrefnum);
InvalRect(&EditR);
}
#else
DestFileName=CurFileName;
if(DoFileSelection())
{ CurHeader->XOrig=0;
CurHeader->YOrig=0;
SimEnd=CurHeader->First;
CurHeader->Last=CurHeader->First;
FileIsNamed= -1;
thefile=fopen(CurFileName,"r");
OpenFile(thefile);
InvalRect(&EditR);
}
#endif
}
void SaveFileAs();
/*
>> Save a file with the name that was previously given
>> or ask for a name, if none was given.
*/
void SaveFile()
{
#ifdef MACINTOSH
char name[256];
int vrefnum;
#endif
if(FileIsNamed)
{
#ifdef MACINTOSH
GetVol(name,&vrefnum);
SetVol(0L,NameOfOpenFile.vRefNum);
BlockMove(1+NameOfOpenFile.fName,name,NameOfOpenFile.fName[0]);
name[NameOfOpenFile.fName[0]]=0;
WriteFile(name);
SetVol(0L,vrefnum);
#else
WriteFile(CurFileName);
#endif
}
else
{ SaveFileAs();
}
}
/*
>> Ask for a filename and call SaveFile.
*/
void SaveFileAs()
{
#ifdef MACINTOSH
Point thepoint = { 80, 160 };
SFPutFile(thepoint,"\p",NameOfOpenFile.fName,0L,&NameOfOpenFile);
if(NameOfOpenFile.good)
{ FileIsNamed= -1;
SetWTitle(MyWind,NameOfOpenFile.fName);
SaveFile();
}
#else
DestFileName=CurFileName;
if(DoFileSelection())
{ FileIsNamed= -1;
SaveFile();
}
#endif
}
/*
>> This routine is complicated, but basically it inserts
>> a new header and circuit data inside a single element
>> on the current level. You can use it to create subchips
>> from files.
*/
Element *InsertCustomChip(name,x,y)
char *name;
int x,y;
{
FILE *thefile;
TableHeader *saved;
long SimBaseOffset,CurHeaderOffset,NewelOffset;
Ptr savedbase;
register Ptr source,dest;
int ins,outs;
register long esize,size;
int namelen,i,width;
Element *newel;
Input *InArray;
#ifdef MACINTOSH
SetPort(MyWind);
TextFont(geneva);
TextSize(9);
TextFace(0);
#endif
/* First extract the file name from the whole path. */
namelen=0;
while(name[namelen++]);
for(i=namelen;i>0 && name[i]!='/';i--);
if(name[i]=='/') i++;
namelen-=i;
/* Look for the file with the given path and the current path. */
thefile=fopen(name,"r");
if(!thefile)
{ name+=i;
i=0;
thefile=fopen(name,"r");
}
width=TextWidth(name,i,namelen-1);
/* Now save the old pointers as offsets while this routine is active. */
SimBaseOffset=SimBase-SimPtr;
CurHeaderOffset=((Ptr) CurHeader)-SimPtr;
/* Create a new base pointer. */
SimBase=SimPtr+SimEnd;
/* Create a new header here. An element structure will later */
/* be inserted before this header. */
esize=(namelen+i+sizeof(long)-1) & ~(sizeof(long)-1); /* force long-word alignment. */
newel=SimAllocate(sizeof(TableHeader)+esize);
CurHeader=(TableHeader *) newel;
CurHeader->PathLen=namelen+i;
CurHeader->First=sizeof(TableHeader)+esize;
CurHeader->TitleLen=namelen;
CurHeader->TitleWidth=width;
/* Copy the whole file name (path). */
source=name;
dest=(Ptr)(CurHeader+1);
size=CurHeader->PathLen;
while(size--)
{ *dest++= *source++;
}
/* Read the circuit from the file. */
NewelOffset=SimBase-(char *)newel;
OpenFile(thefile);
newel=(Element *)(SimBase+NewelOffset);
CurHeader->Last=SimPtr+SimEnd-SimBase;
ins=CountElementType(INPT); /* Count input pins. */
outs=CountElementType(OUTP); /* Count output pins. */
/* Now we know how large the element will be. */
esize=sizeof(Element)+(outs-1)*sizeof(Output)+ins*sizeof(Input);
/* Allocate room for the element. */
NewelOffset=SimBase-(char *)newel;
SimAllocate(esize);
newel=(Element *)(SimBase+NewelOffset);
/* Insert the element before the header and the data. */
dest=SimPtr+SimEnd;
source=dest-esize;
size=CurHeader->Last;
while(size--)
{ *--dest= *--source;
}
esize+=CurHeader->Last;
/* Set element structure values. */
newel->Flags=0;
newel->Type=CUST;
newel->Length=esize;
newel->Inputs=ins;
newel->Outputs=outs;
PresetElement(newel,x,y,(width+31) & ~31);
/* Fill in inputs and outputs with default values. */
InArray=(Input *)&(newel->Out[outs]);
while(ins--)
{ InArray->Chip=0;
InArray->Pin=0;
InArray++;
}
while(outs--)
{ newel->Out[outs].Data=0;
}
/* Restore previous header pointers from offsets. */
SimBase=SimPtr+SimBaseOffset;
CurHeader=(TableHeader *)(SimPtr+CurHeaderOffset);
/* Advance pointer of last item in current header. */
CurHeader->Last=SimPtr-SimBase+SimEnd;
return newel;
}
static char CustomFileName[2048];
/*
>> Ask for a file name of a custom chip and add that
>> to the center of the edit area.
*/
void AddCustomChip()
{
int x,y;
Element *custel;
#ifdef MACINTOSH
SFReply customname;
int vrefnum;
long thetype='TEXT';
Point thepoint={64,64};
char name[256];
SFGetFile(thepoint,"\p",0L,1,&thetype,0L,&customname);
if(customname.good)
{ GetVol(name,&vrefnum);
SetVol(0L,customname.vRefNum);
BlockMove(1+customname.fName,name,customname.fName[0]);
name[customname.fName[0]]=0;
x=((EditR.right-EditR.left)/2+CurHeader->XOrig) & ~7;
y=((EditR.bottom-EditR.top)/2+CurHeader->XOrig) & ~7;
ClipEditArea();
custel=InsertCustomChip(name,x,y);
SetTrashRect(&custel->Body);
InvalTrash();
RestoreClipping();
SetVol(0L,vrefnum);
}
#else
DestFileName=CustomFileName;
if(DoFileSelection())
{ x=((EditR.right-EditR.left)/2+CurHeader->XOrig) & ~7;
y=((EditR.bottom-EditR.top)/2+CurHeader->XOrig) & ~7;
ClipEditArea();
custel=InsertCustomChip(CustomFileName,x,y);
SetTrashRect(&custel->Body);
InvalTrash();
RestoreClipping();
}
#endif
}